package com.zl.bootsecurityjwt.common.config;

import com.alibaba.fastjson.JSONObject;
import com.zl.bootsecurityjwt.common.constant.HttpStatus;
import com.zl.bootsecurityjwt.common.utils.ResponseMapUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Map;

import static com.zl.bootsecurityjwt.common.jwt.JwtTokenFilter.HEADER_STRING;

@Slf4j
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {

    private static final long serialVersionUID = -8970718410437077606L;

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException {
        StringBuilder msg = new StringBuilder();
        String token=httpServletRequest.getHeader(HEADER_STRING);
//        msg.append(httpServletRequest.getRequestURI()).append(" 接口， 经jwt 认证失败，无法访问系统资源.");
        //log.info(e.toString());
        //通过设置响应头控制浏览器以UTF-8的编码显示数据，如果不加这句话，那么浏览器显示的将是乱码
        response.setHeader("content-type", "text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
        /**
         * PrintWriter out = response.getWriter();这句代码必须放在response.setCharacterEncoding("UTF-8");之后
         * 否则response.setCharacterEncoding("UTF-8")这行代码的设置将无效，浏览器显示的时候还是乱码
         */
        PrintWriter out = response.getWriter();//获取PrintWriter输出流
        // 用户登录时身份认证未通过
        if (e instanceof BadCredentialsException) {
            log.info("用户登录时身份认证失败，请从新输入....");
            Map<String, Object> map = ResponseMapUtil.getResponseMap(httpServletRequest.getRequestURI(), HttpStatus.NOT_FOUND, "用户登录时身份认证失败!");
            out.write(JSONObject.toJSONString(map));//使用PrintWriter流向客户端输出字符
        } else if (e instanceof InsufficientAuthenticationException && token==null) {
            log.info("缺少请求头参数,Authorization传递是token值所以参数是必须的.");
            Map<String, Object> map = ResponseMapUtil.getResponseMap(httpServletRequest.getRequestURI(), HttpStatus.UNAUTHORIZED, "缺少请求头参数,Authorization传递是token值所以参数是必须的!");
            out.write(JSONObject.toJSONString(map));//使用PrintWriter流向客户端输出字符
        }
        else {
            log.info("用户token无效，请从新输入....");
            Map<String, Object> map = ResponseMapUtil.getResponseMap(httpServletRequest.getRequestURI(), HttpStatus.NOT_FOUND, "用户token无效!");
            out.write(JSONObject.toJSONString(map));//使用PrintWriter流向客户端输出字符
        }

    }
}
